package com.tul.vapp.servicecenter.service.impl;

import com.tul.cusa.common.util.DateUtil;
import com.tul.cusa.common.util.ListUtil;
import com.tul.cusa.common.util.StringUtil;
import com.tul.vapp.servicecenter.dao.IAppDao;
import com.tul.vapp.servicecenter.dao.IItemDao;
import com.tul.vapp.servicecenter.dao.INamespaceDao;
import com.tul.vapp.servicecenter.dao.IReleaseItemDao;
import com.tul.vapp.servicecenter.entity.Item;
import com.tul.vapp.servicecenter.entity.ItemVo;
import com.tul.vapp.servicecenter.entity.Namespace;
import com.tul.vapp.servicecenter.entity.Status;
import com.tul.vapp.servicecenter.service.IItemService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 操作数据库中的配置项
 *
 * @author wwxiang
 * @since 2018/1/4.
 */
@Service
public class ItemService implements IItemService {

    @Autowired
    private IItemDao itemDao;

    @Autowired
    private IReleaseItemDao releaseItemDao;
    @Autowired
    private INamespaceDao namespaceDao;
    @Autowired
    private IAppDao appDao;

    @Override
    public boolean addItem(String appId, String namespace, String keyName, String value) {
        Item item = new Item();
        item.setAppId(appId);
        item.setNamespace(namespace);
        item.setKeyName(keyName);
        item.setValue(value);
        item.setStatus(Status.INSERT);
        item.setCreateTime(DateUtil.format(new Date(), DateUtil.DATE_TIME_FORMAT));
        itemDao.addItem(item);
        return true;
    }

    @Override
    public List<Item> getItems(String appId, String namespace) {

        if (StringUtil.isEmpty(appId)) {
            throw new IllegalArgumentException("AppId can't be empty.");
        }

        if (StringUtil.isEmpty(namespace)) {
            throw new IllegalArgumentException("Namespace can't be empty.");
        }

        return itemDao.getItems(appId, namespace);
    }

    @Override
    public List<ItemVo> getItemVos(String appId, String namespace) {
        int namespaceId = namespaceDao.getNamespace(appId, namespace).getId();
        List<ItemVo> itemVos = new ArrayList();
        for (Item item : itemDao.getItems(appId, namespace)) {
            ItemVo itemVo = new ItemVo();
            itemVo.setId(item.getId());
            itemVo.setAppId(item.getAppId());
            itemVo.setAid(appDao.getApp(appId).getId());
            itemVo.setComment(item.getComment());
            itemVo.setKeyName(item.getKeyName());
            itemVo.setValue(item.getValue());
            itemVo.setNamespaceId(namespaceId);
            itemVo.setNamespace(namespace);
            if (item.getNeedRestart() == 1) {
                itemVo.setNeedRestart(true);
            } else {
                itemVo.setNeedRestart(false);
            }
            itemVo.setStatus(item.getStatus());
            itemVo.setUpdateTime(item.getUpdateTime());
            if (item.getStatus() == 0) {
                itemVo.setRelease(true);
            } else {
                itemVo.setRelease(false);
            }
            itemVos.add(itemVo);
        }
        return itemVos;
    }

    @Override
    public List<Item> getReleaseItems(String appId, String namespace) {

        if (StringUtil.isEmpty(appId)) {
            throw new IllegalArgumentException("AppId can't be empty.");
        }

        if (StringUtil.isEmpty(namespace)) {
            throw new IllegalArgumentException("Namespace can't be empty.");
        }

        return releaseItemDao.getItems(appId, namespace);
    }

    @Override
    public void update(ItemVo itemVo) {
        Item item = itemDao.getItem(itemVo.getAppId(), itemVo.getNamespace(), itemVo.getKeyName());
        item.setValue(itemVo.getValue());
        item.setStatus(Status.MODIFY);
        item.setComment(itemVo.getComment());
        item.setUpdateTime(DateUtil.format(new Date(), DateUtil.DATE_TIME_FORMAT));
        itemDao.updateItem(item);
    }

    @Override
    public void update(String appId, String namespace, String keyName, String newValue) {
        if (StringUtil.isEmpty(appId)) {
            throw new IllegalArgumentException("AppId can't be empty.");
        }
        if (StringUtil.isEmpty(namespace)) {
            throw new IllegalArgumentException("Namespace can't be empty.");
        }
        if (StringUtil.isEmpty(keyName)) {
            throw new IllegalArgumentException("KeyName can't be empty.");
        }
        if (StringUtil.isEmpty(newValue)) {
            throw new IllegalArgumentException("NewValue can't be empty.");
        }

        Item item = new Item();
        item.setAppId(appId);
        item.setNamespace(namespace);
        item.setKeyName(keyName);
        item.setValue(newValue);
        item.setStatus(Status.MODIFY);
        item.setUpdateTime(DateUtil.format(new Date(), DateUtil.DATE_TIME_FORMAT));
        itemDao.updateItem(item);
    }

    @Override
    public void delete(String appId, String namespace, String keyName) {
        itemDao.deleteItem(appId, namespace, keyName);
    }

    @Override
    public void deleteItems(String appId, String namespace) {
        itemDao.deleteItemInNs(appId, namespace);
    }

    @Override
    public void publish(String appId, String namespace) {
        List<Item> items = itemDao.getItems(appId, namespace);
        for (Item item : items) {
            if (item.getStatus() == Status.PUBLISHED) {
                // 状态为已发布的，跳过
                continue;
            }

            item.setUpdateTime(DateUtil.format(new Date(), DateUtil.DATE_TIME_FORMAT));
            if (item.getStatus() == Status.DELETE) {
                // 已标记删除的，直接删除
                itemDao.deleteItem(appId, namespace, item.getKeyName());
                releaseItemDao.deleteItem(appId, namespace, item.getKeyName());
            } else if (item.getStatus() == Status.INSERT) {
                // 标记为新增的，操作表 状态更新为PUBLISHED，发布表插入
                item.setStatus(Status.PUBLISHED);
                itemDao.updateItem(item);
                releaseItemDao.addItem(item);
            } else if (item.getStatus() == Status.MODIFY) {
                // 标记为修改的，操作表 状态更新为PUBLISHED，发布表更新
                item.setStatus(Status.PUBLISHED);
                itemDao.updateItem(item);

                // release表中已存在则更新，否则新增
                Item it = releaseItemDao.getItem(appId, namespace, item.getKeyName());
                if (it != null) {
                    releaseItemDao.updateItem(item);
                } else {
                    releaseItemDao.addItem(item);
                }
            }
        }
    }

    @Override
    public List<Namespace> getModifiedNamespace() {
        return itemDao.getModifiedNamespace();
    }

    @Override
    public void rollback(String appId, String namespace) {
        List<Item> items = itemDao.getItems(appId, namespace);
        for (Item item : items) {
            if (item.getStatus() == Status.DELETE) {
                // 标记为删除的，只需要将操作表状态回退到published
                item.setStatus(Status.PUBLISHED);
                itemDao.updateItem(item);
            } else if (item.getStatus() == Status.INSERT) {
                // 标记为新增的，回退时，将此数据删除
                itemDao.deleteItem(item.getAppId(), item.getNamespace(), item.getKeyName());
            } else if (item.getStatus() == Status.MODIFY) {
                // 标记为修改的，回退到release
                Item release = releaseItemDao.getItem(item.getAppId(), item.getNamespace(), item.getKeyName());
                itemDao.updateItem(release);
            }
        }
    }

    @Override
    public void sanityCheck(String appId, String namespace) {
        // 已发布的数据
        List<Item> itemReleaseObj = releaseItemDao.getItems(appId, namespace);
        List<String> itemRelease = new ArrayList();
        for (Item item : itemReleaseObj) {
            itemRelease.add(item.getKeyName());
        }

        // 操作表内的数据
        List<Item> itemObj = itemDao.getItems(appId, namespace);
        List<String> items = new ArrayList();
        for (Item item : itemObj) {
            items.add(item.getKeyName());
        }

        // 发布表比操作表里多，是需要处理的
        List<String> adds = ListUtil.subtract(itemRelease, items);
        for (String add : adds) {
            Item i = releaseItemDao.getItem(appId, namespace, add);
            itemDao.addItem(i);
        }
    }
}
